package com.example.mybatisplus.plugs;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.example.mybatisplus.common.RealtyDataPermission;
import com.example.mybatisplus.utils.UserContextHolder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;

import java.util.Objects;

/**
 * 数据权限控制器
 *
 * @author zc
 * @since 2021-12-10 13:28
 */
@Slf4j
public class MyDataPermissionHandler implements DataPermissionHandler {

    @Override
    @SneakyThrows
    public Expression getSqlSegment(Expression where, String mappedStatementId) {
        // 仅对查询方法生效，非查询直接放行
        if (!isQueryMethod(mappedStatementId)) {
            return where;
        }
        // 判断是否是登录获取数据，是则不进行数据权限控制
        Boolean flag = UserContextHolder.get();
        if (flag) {
            UserContextHolder.clear();
            return where;
        }
        Class<?> clazz = Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(StringPool.DOT)));

        if (!clazz.isAnnotationPresent(RealtyDataPermission.class)) {
            log.info("RealtyDataPermission not present");
            return where;
        }

        RealtyDataPermission realtyDataPermission = clazz.getAnnotation(RealtyDataPermission.class);
        String type = realtyDataPermission.type();
        String field = realtyDataPermission.field();

        String perValue;
        if (Objects.equals(type, "customer")) {
            perValue = "(1140)";
        } else if (Objects.equals(type, "stall")) {
            perValue = "(1,2)";
        } else {
            return where;
        }
        String appendSqlStr = field + " in " + perValue;

        if (StrUtil.isBlank(appendSqlStr)) {
            return where;
        }

        Expression appendExpression = CCJSqlParserUtil.parseCondExpression(appendSqlStr);

        if (where == null) {
            return appendExpression;
        }

        return new AndExpression(where, appendExpression);

    }

    private boolean isQueryMethod(String mappedStatementId) {
        if (mappedStatementId == null || !mappedStatementId.contains(StringPool.DOT)) {
            return false;
        }
        String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(StringPool.DOT) + 1).toLowerCase();
        String[] queryPrefixes = {"select", "get", "find", "list", "page", "query", "count", "search"};
        for (String p : queryPrefixes) {
            if (methodName.startsWith(p)) {
                return true;
            }
        }
        return false;
    }

}

